#include "muxer_mp4_read.h"
#include "base_log.h"
#include <chrono>

namespace El {
namespace Muxer {

MP4Read::MP4Read()
    : format_ctx(nullptr,
                 [](AVFormatContext *ctx) {
                     avformat_close_input(&ctx);
                     avformat_free_context(ctx);
                 }),
      video_codec_ctx(nullptr, [](AVCodecContext *ctx) { avcodec_free_context(&ctx); }),
      video_packet(nullptr, [](AVPacket *pkt) { av_packet_free(&pkt); }),
      video_bsf_ctx(nullptr, [](AVBSFContext *ctx) { av_bsf_free(&ctx); }),
      audio_codec_ctx(nullptr, [](AVCodecContext *ctx) { avcodec_free_context(&ctx); }),
      audio_bsf_ctx(nullptr, [](AVBSFContext *ctx) { av_bsf_free(&ctx); })
{
}

MP4Read::~MP4Read()
{
    Stop();
    Close();
}

bool MP4Read::Open(const std::string &inputFile)
{
    input_file = inputFile;

    // Open input file
    if (avformat_open_input(&format_ctx_raw, input_file.c_str(), nullptr, nullptr) != 0) {
        LOG_ERROR("Unable to open input file.");
        return false;
    }

    format_ctx.reset(format_ctx_raw);

    if (avformat_find_stream_info(format_ctx.get(), nullptr) < 0) {
        LOG_ERROR("Unable to find stream information.");
        return false;
    }

    // Find video stream
    video_stream_index = -1;
    for (unsigned int i = 0; i < format_ctx->nb_streams; i++) {
        const AVCodecParameters *codecpar = format_ctx->streams[i]->codecpar;
        if (codecpar->codec_type == AVMEDIA_TYPE_VIDEO) {
            video_stream_index = i;
            video_codec = avcodec_find_decoder(codecpar->codec_id);
            break;
        }
    }

    if (video_stream_index != -1) {
        // Create video codec context
        video_codec_ctx.reset(avcodec_alloc_context3(video_codec));

        if (!video_codec_ctx) {
            LOG_ERROR("Unable to allocate video codec context.");
            return false;
        }

        if (avcodec_parameters_to_context(video_codec_ctx.get(), format_ctx->streams[video_stream_index]->codecpar) <
            0) {
            LOG_ERROR("Unable to copy video codec parameters to context.");
            return false;
        }

        if (avcodec_open2(video_codec_ctx.get(), video_codec, nullptr) < 0) {
            LOG_ERROR("Unable to open video codec.");
            return false;
        }

        video_packet.reset(av_packet_alloc());

        // Initialize video bitstream filter
        const char *bsf_name = nullptr;
        if (video_codec_ctx->codec_id == AV_CODEC_ID_H264) {
            bsf_name = "h264_mp4toannexb";
        } else if (video_codec_ctx->codec_id == AV_CODEC_ID_HEVC) {
            bsf_name = "hevc_mp4toannexb";
        } else {
            LOG_ERROR("Unsupported video codec.");
            return false;
        }

        video_bsf = av_bsf_get_by_name(bsf_name);
        if (!video_bsf) {
            LOG_ERROR("Cannot find video bsf: {}", bsf_name);
            return false;
        } else {
            LOG_DEBUG("Found video bsf: {}", bsf_name);
        }

        if (av_bsf_alloc(video_bsf, &video_bsf_ctx_raw) < 0) {
            LOG_ERROR("Unable to allocate video bitstream filter context.");
            return false;
        }

        video_bsf_ctx.reset(video_bsf_ctx_raw);

        if (avcodec_parameters_copy(video_bsf_ctx->par_in, format_ctx->streams[video_stream_index]->codecpar) < 0) {
            LOG_ERROR("Unable to copy video codec parameters to bitstream filter context.");
            return false;
        }

        video_bsf_ctx->time_base_in = format_ctx->streams[video_stream_index]->time_base;

        if (av_bsf_init(video_bsf_ctx.get()) < 0) {
            LOG_ERROR("Unable to initialize video bitstream filter context.");
            return false;
        }
    } else {
        LOG_WARN("No video stream found.");
    }

    // Find audio stream
    audio_stream_index = -1;
    for (unsigned int i = 0; i < format_ctx->nb_streams; i++) {
        const AVCodecParameters *codecpar = format_ctx->streams[i]->codecpar;
        if (codecpar->codec_type == AVMEDIA_TYPE_AUDIO) {
            audio_stream_index = i;
            audio_codec = avcodec_find_decoder(codecpar->codec_id);
            break;
        }
    }

    if (audio_stream_index != -1) {
        // Create audio codec context
        audio_codec_ctx.reset(avcodec_alloc_context3(audio_codec));

        if (!audio_codec_ctx) {
            LOG_ERROR("Unable to allocate audio codec context.");
            return false;
        }

        if (avcodec_parameters_to_context(audio_codec_ctx.get(), format_ctx->streams[audio_stream_index]->codecpar) <
            0) {
            LOG_ERROR("Unable to copy audio codec parameters to context.");
            return false;
        }

        if (avcodec_open2(audio_codec_ctx.get(), audio_codec, nullptr) < 0) {
            LOG_ERROR("Unable to open audio codec.");
            return false;
        }

        // Initialize audio bitstream filter
        const char *audio_bsf_name = nullptr;
        if (audio_codec_ctx->codec_id == AV_CODEC_ID_AAC) {
            audio_bsf_name = "aac_adtstoasc";
        } else if (audio_codec_ctx->codec_id == AV_CODEC_ID_MP3) {
            audio_bsf_name = "mp3decomp";
        } else if (audio_codec_ctx->codec_id == AV_CODEC_ID_PCM_ALAW ||
                   audio_codec_ctx->codec_id == AV_CODEC_ID_PCM_MULAW) {
            // G.711 A-law or μ-law encoding
            // Usually no bitstream filter is needed, but if there are special requirements, it can be added here
            audio_bsf_name = nullptr; // No filter needed
        } else {
            LOG_ERROR("Unsupported audio codec.");
            return false;
        }

        if (audio_bsf_name) {
            audio_bsf = av_bsf_get_by_name(audio_bsf_name);
            if (!audio_bsf) {
                LOG_ERROR("Unable to find audio bitstream filter: {}", audio_bsf_name);
                return false;
            } else {
                LOG_INFO("Found audio bitstream filter: {}", audio_bsf_name);
            }

            if (av_bsf_alloc(audio_bsf, &audio_bsf_ctx_raw) < 0) {
                LOG_ERROR("Unable to allocate audio bitstream filter context.");
                return false;
            }

            audio_bsf_ctx.reset(audio_bsf_ctx_raw);

            if (avcodec_parameters_copy(audio_bsf_ctx->par_in, format_ctx->streams[audio_stream_index]->codecpar) < 0) {
                LOG_ERROR("Unable to copy audio codec parameters to bitstream filter context.");
                return false;
            }

            audio_bsf_ctx->time_base_in = format_ctx->streams[audio_stream_index]->time_base;

            if (av_bsf_init(audio_bsf_ctx.get()) < 0) {
                LOG_ERROR("Unable to initialize audio bitstream filter context.");
                return false;
            }
        }
    } else {
        LOG_DEBUG("No audio stream found.");
    }

    return true;
}

bool MP4Read::RegisterVideoCallback(std::function<void(const Media::MediaFramePtr &)> videoCallback)
{
    std::lock_guard<std::mutex> lock(callback_mutex);
    video_callback = videoCallback;
    return true;
}

bool MP4Read::RegisterAudioCallback(std::function<void(const Media::MediaFramePtr &)> audioCallback)
{
    std::lock_guard<std::mutex> lock(callback_mutex);
    audio_callback = audioCallback;
    return true;
}

bool MP4Read::Start(bool loop)
{
    if (is_running.load()) {
        LOG_ERROR("Conversion is already running.");
        return false;
    }

    is_running.store(true);
    should_loop.store(loop); // Store loop flag
    processing_thread = std::thread(&MP4Read::ProcessingLoop, this);
    return true;
}

void MP4Read::Stop()
{
    if (!is_running.load()) {
        return;
    }

    is_running.store(false);
    is_paused_.store(false); // 重置暂停状态
    last_video_pts_ = 0;     // 重置pts时间
    last_audio_pts_ = 0;
    if (processing_thread.joinable()) {
        processing_thread.join();
    }
}

void MP4Read::ProcessingLoop()
{
    AVPacket *pkt = av_packet_alloc();
    if (!pkt) {
        LOG_ERROR("Unable to allocate AVPacket.");
        return;
    }

    uint64_t total_video_pts = 0;
    uint64_t total_audio_pts = 0;

    do { // Use do-while loop to support repeated playback
        // Reset file position to the beginning
        if (av_seek_frame(format_ctx.get(), -1, 0, AVSEEK_FLAG_BACKWARD) < 0) {
            LOG_ERROR("Unable to reset file position to the beginning.");
            break;
        }

        // Reset first frame flags
        is_first_video_frame = true;
        is_first_audio_frame = true;

        while (is_running.load()) {
            // 处理暂停状态
            if (is_paused_.load()) {
                std::this_thread::sleep_for(std::chrono::milliseconds(10));
                continue;
            }

            int ret = av_read_frame(format_ctx.get(), pkt);
            if (ret < 0) {
                // End of file or error occurred
                if (ret == AVERROR_EOF) {
                    LOG_INFO("Reached end of file.");
                    break; // Exit inner loop, will restart if looping is enabled
                } else {
                    LOG_ERROR("Unable to read AVPacket. Error code: {}", ret);
                    is_running.store(false);
                    break;
                }
            }

            if (pkt->stream_index == video_stream_index && video_stream_index != -1) {
                ProcessVideoPacket(pkt, total_video_pts);
            } else if (pkt->stream_index == audio_stream_index && audio_stream_index != -1) {
                ProcessAudioPacket(pkt, total_audio_pts);
            }

            av_packet_unref(pkt);
        }

        if (should_loop.load() && is_running.load()) {
            // Update total PTS to maintain continuity
            AVRational video_time_base = format_ctx->streams[video_stream_index]->time_base;
            AVRational audio_time_base = format_ctx->streams[audio_stream_index]->time_base;

            total_video_pts += av_rescale_q(format_ctx->duration, AV_TIME_BASE_Q, video_time_base);
            total_audio_pts += av_rescale_q(format_ctx->duration, AV_TIME_BASE_Q, audio_time_base);
        }
    } while (should_loop.load() && is_running.load()); // Decide whether to continue playing based on loop flag

    av_packet_free(&pkt);
}

void MP4Read::ProcessVideoPacket(AVPacket *pkt, uint64_t &total_pts)
{
    AVRational time_base = format_ctx->streams[video_stream_index]->time_base;

    if (av_bsf_send_packet(video_bsf_ctx.get(), pkt) < 0) {
        LOG_ERROR("Error sending video packet to bitstream filter.");
        return;
    }

    while (av_bsf_receive_packet(video_bsf_ctx.get(), pkt) == 0) {
        pkt->pts += total_pts;
        pkt->dts += total_pts;

        int64_t pts_time = av_rescale_q(pkt->pts, time_base, AV_TIME_BASE_Q);
        LOG_TRACE("Video frame PTS time: {} microseconds", pts_time);

        // 更新最后一帧的pts时间
        last_video_pts_ = pts_time;

        if (is_first_video_frame) {
            video_start_time = std::chrono::steady_clock::now() - std::chrono::microseconds(pts_time);
            is_first_video_frame = false;
        }

        // 只有在非暂停状态下才进行时间控制
        if (!is_paused_.load()) {
            auto frame_time = video_start_time + std::chrono::microseconds(pts_time);
            auto now = std::chrono::steady_clock::now();
            if (frame_time > now) {
                std::this_thread::sleep_until(frame_time);
            }
        }

        auto frame = std::make_shared<Media::MediaFrame>();
        if (!frame->PutBuffer(pkt->data, pkt->size)) {
            LOG_ERROR("Failed to put buffer");
            return;
        }
        frame->SetFrameType((pkt->flags & AV_PKT_FLAG_KEY) ? MEDIA_FRAME_I : MEDIA_FRAME_P);
        frame->SetCodecType((video_codec_ctx->codec_id == AV_CODEC_ID_H264)   ? MEDIA_VIDEO_CODEC_H264
                            : (video_codec_ctx->codec_id == AV_CODEC_ID_HEVC) ? MEDIA_VIDEO_CODEC_H265
                                                                              : MEDIA_VIDEO_CODEC_UNKOWN);
        AVRational frame_rate = format_ctx->streams[video_stream_index]->avg_frame_rate;
        frame->SetFrameRate(av_q2d(frame_rate));
        frame->SetPts(static_cast<uint64_t>(pkt->pts * av_q2d(time_base) * 1e6));
        frame->SetUtc(static_cast<uint64_t>(
            std::chrono::duration_cast<std::chrono::microseconds>(std::chrono::steady_clock::now().time_since_epoch())
                .count()));

        {
            std::lock_guard<std::mutex> lock(callback_mutex);
            if (video_callback) {
                video_callback(frame);
            }
        }

        av_packet_unref(pkt);

        if (!is_running.load()) {
            break;
        }
    }
}

void MP4Read::ProcessAudioPacket(AVPacket *pkt, uint64_t &total_pts)
{
    AVRational time_base = format_ctx->streams[audio_stream_index]->time_base;

    pkt->pts += total_pts;
    pkt->dts += total_pts;

    if (audio_bsf_ctx) {
        // Process with bitstream filter
        if (av_bsf_send_packet(audio_bsf_ctx.get(), pkt) < 0) {
            LOG_ERROR("Error sending audio packet to bitstream filter.");
            return;
        }

        while (av_bsf_receive_packet(audio_bsf_ctx.get(), pkt) == 0) {
            double pts_time = pkt->pts * av_q2d(time_base) * 1e6;

            // 更新最后一帧的pts时间
            last_audio_pts_ = static_cast<int64_t>(pts_time);

            if (is_first_audio_frame) {
                audio_start_time =
                    std::chrono::steady_clock::now() - std::chrono::microseconds(static_cast<int64_t>(pts_time));
                is_first_audio_frame = false;
            }

            // 只有在非暂停状态下才进行时间控制
            if (!is_paused_.load()) {
                auto frame_time = audio_start_time + std::chrono::microseconds(static_cast<int64_t>(pts_time));
                auto now = std::chrono::steady_clock::now();
                if (frame_time > now) {
                    std::this_thread::sleep_until(frame_time);
                }
            }

            std::vector<uint8_t> data;
            data.assign(pkt->data, pkt->data + pkt->size);

            // Add ADTS header for AAC
            if (audio_codec_ctx->codec_id == AV_CODEC_ID_AAC) {
                std::vector<uint8_t> adts_header = GenerateADTSHeader(pkt->size, audio_codec_ctx->sample_rate);
                data.insert(data.begin(), adts_header.begin(), adts_header.end());
            }

            auto frame = std::make_shared<Media::MediaFrame>();
            if (!frame->PutBuffer(data.data(), data.size())) {
                LOG_ERROR("Failed to put buffer");
                return;
            }
            frame->SetCodecType((audio_codec_ctx->codec_id == AV_CODEC_ID_AAC)         ? MEDIA_AUDIO_CODEC_AAC
                                : (audio_codec_ctx->codec_id == AV_CODEC_ID_PCM_ALAW)  ? MEDIA_AUDIO_CODEC_G711A
                                : (audio_codec_ctx->codec_id == AV_CODEC_ID_PCM_MULAW) ? MEDIA_AUDIO_CODEC_G711U
                                                                                       : MEDIA_AUDIO_CODEC_UNKOWN);
            frame->SetFrameType((audio_codec_ctx->codec_id == AV_CODEC_ID_AAC)         ? MEDIA_FRAME_AAC
                                : (audio_codec_ctx->codec_id == AV_CODEC_ID_PCM_ALAW)  ? MEDIA_FRAME_G711A
                                : (audio_codec_ctx->codec_id == AV_CODEC_ID_PCM_MULAW) ? MEDIA_FRAME_G711U
                                                                                       : MEDIA_FRAME_UNKOWN);
            frame->SetFrameRate(static_cast<double>(audio_codec_ctx->sample_rate));
            frame->SetPts(static_cast<uint64_t>(pkt->pts * av_q2d(time_base) * 1e6));
            frame->SetUtc(static_cast<uint64_t>(std::chrono::duration_cast<std::chrono::microseconds>(
                                                    std::chrono::steady_clock::now().time_since_epoch())
                                                    .count()));

            {
                std::lock_guard<std::mutex> lock(callback_mutex);
                if (audio_callback) {
                    audio_callback(frame);
                }
            }

            av_packet_unref(pkt);

            if (!is_running.load()) {
                break;
            }
        }
    } else {
        // Process raw audio packet (e.g. G.711)
        double pts_time = pkt->pts * av_q2d(time_base) * 1e6;

        // 更新最后一帧的pts时间
        last_audio_pts_ = static_cast<int64_t>(pts_time);

        if (is_first_audio_frame) {
            audio_start_time =
                std::chrono::steady_clock::now() - std::chrono::microseconds(static_cast<int64_t>(pts_time));
            is_first_audio_frame = false;
        }

        // 只有在非暂停状态下才进行时间控制
        if (!is_paused_.load()) {
            auto frame_time = audio_start_time + std::chrono::microseconds(static_cast<int64_t>(pts_time));
            auto now = std::chrono::steady_clock::now();
            if (frame_time > now) {
                std::this_thread::sleep_until(frame_time);
            }
        }

        auto frame = std::make_shared<Media::MediaFrame>();
        if (!frame->PutBuffer(pkt->data, pkt->size)) {
            LOG_ERROR("Failed to put buffer");
            return;
        }
        frame->SetCodecType((audio_codec_ctx->codec_id == AV_CODEC_ID_AAC)         ? MEDIA_AUDIO_CODEC_AAC
                            : (audio_codec_ctx->codec_id == AV_CODEC_ID_PCM_ALAW)  ? MEDIA_AUDIO_CODEC_G711A
                            : (audio_codec_ctx->codec_id == AV_CODEC_ID_PCM_MULAW) ? MEDIA_AUDIO_CODEC_G711U
                                                                                   : MEDIA_AUDIO_CODEC_UNKOWN);
        frame->SetFrameType((audio_codec_ctx->codec_id == AV_CODEC_ID_AAC)         ? MEDIA_FRAME_AAC
                            : (audio_codec_ctx->codec_id == AV_CODEC_ID_PCM_ALAW)  ? MEDIA_FRAME_G711A
                            : (audio_codec_ctx->codec_id == AV_CODEC_ID_PCM_MULAW) ? MEDIA_FRAME_G711U
                                                                                   : MEDIA_FRAME_UNKOWN);
        frame->SetFrameRate(static_cast<double>(audio_codec_ctx->sample_rate));
        frame->SetPts(static_cast<uint64_t>(pkt->pts * av_q2d(time_base) * 1e6));
        frame->SetUtc(static_cast<uint64_t>(
            std::chrono::duration_cast<std::chrono::microseconds>(std::chrono::steady_clock::now().time_since_epoch())
                .count()));

        {
            std::lock_guard<std::mutex> lock(callback_mutex);
            if (audio_callback) {
                audio_callback(frame);
            }
        }

        av_packet_unref(pkt);
    }

    // Check if stopped running
    if (!is_running.load()) {
        return;
    }
}

std::vector<uint8_t> MP4Read::GenerateADTSHeader(int aac_data_length, int sample_rate)
{
    int profile = 2; // AAC LC
    int freqIdx = GetFrequencyIndex(sample_rate);
    if (freqIdx == -1) {
        LOG_ERROR("Unsupported sample rate: {}", sample_rate);
        // Use 44.1KHz by default
        freqIdx = 4;
    }
    int chanCfg = audio_codec_ctx->channels;
    int frameLength = aac_data_length + 7;

    std::vector<uint8_t> adts_header(7);
    adts_header[0] = 0xFF;
    adts_header[1] = 0xF1;
    adts_header[2] = (char)(((profile - 1) << 6) + (freqIdx << 2) + (chanCfg >> 2));
    adts_header[3] = (char)(((chanCfg & 3) << 6) + (frameLength >> 11));
    adts_header[4] = (char)((frameLength & 0x7FF) >> 3);
    adts_header[5] = (char)(((frameLength & 7) << 5) + 0x1F);
    adts_header[6] = 0xFC;

    return adts_header;
}

int MP4Read::GetFrequencyIndex(int sample_rate)
{
    switch (sample_rate) {
        case 96000:
            return 0;
        case 88200:
            return 1;
        case 64000:
            return 2;
        case 48000:
            return 3;
        case 44100:
            return 4;
        case 32000:
            return 5;
        case 24000:
            return 6;
        case 22050:
            return 7;
        case 16000:
            return 8;
        case 12000:
            return 9;
        case 11025:
            return 10;
        case 8000:
            return 11;
        case 7350:
            return 12;
        default:
            return -1; // Unsupported sample rate
    }
}

void MP4Read::Close()
{
    Stop();

    format_ctx.reset();
    video_codec_ctx.reset();
    video_packet.reset();
    video_bsf_ctx.reset();
    audio_codec_ctx.reset();
    audio_bsf_ctx.reset();

    is_first_video_frame = true;
    is_first_audio_frame = true;
}

bool MP4Read::GetVideoInfo(VideoEncFormat &video)
{
    if (video_stream_index == -1 || !video_codec_ctx) {
        LOG_ERROR("Video stream not initialized.");
        return false;
    }

    // Get codec type
    switch (video_codec_ctx->codec_id) {
        case AV_CODEC_ID_H264:
            video.codecType = MEDIA_VIDEO_CODEC_H264;
            break;
        case AV_CODEC_ID_HEVC:
            video.codecType = MEDIA_VIDEO_CODEC_H265;
            break;
        default:
            video.codecType = MEDIA_VIDEO_CODEC_UNKOWN;
    }

    // Get width and height
    video.width = video_codec_ctx->width;
    video.height = video_codec_ctx->height;

    // Get frame rate
    AVRational frame_rate = format_ctx->streams[video_stream_index]->avg_frame_rate;
    video.fps = av_q2d(frame_rate);

    return true;
}

bool MP4Read::GetAudioInfo(AudioEncFormat &audio)
{
    if (audio_stream_index == -1 || !audio_codec_ctx) {
        LOG_ERROR("Audio stream not initialized.");
        return false;
    }

    // Get codec type
    switch (audio_codec_ctx->codec_id) {
        case AV_CODEC_ID_AAC:
            audio.codecType = MEDIA_AUDIO_CODEC_AAC;
            break;
        case AV_CODEC_ID_MP3:
            audio.codecType = MEDIA_AUDIO_CODEC_MP3;
            break;
        case AV_CODEC_ID_PCM_ALAW:
            audio.codecType = MEDIA_AUDIO_CODEC_G711A;
            break;
        case AV_CODEC_ID_PCM_MULAW:
            audio.codecType = MEDIA_AUDIO_CODEC_G711U;
            break;
        default:
            audio.codecType = MEDIA_AUDIO_CODEC_UNKOWN;
    }

    // Get sample rate
    audio.sampleRate = audio_codec_ctx->sample_rate;

    // Get number of channels
    audio.channels = audio_codec_ctx->channels;

    return true;
}

int64_t MP4Read::GetDuration() const
{
    if (!format_ctx) {
        return 0;
    }

    // 获取视频流的时长
    if (video_stream_index >= 0) {
        AVStream *video_stream = format_ctx->streams[video_stream_index];
        if (video_stream->duration != AV_NOPTS_VALUE) {
            // 将时间基转换为毫秒
            return av_rescale_q(video_stream->duration, video_stream->time_base, AVRational{1, 1000}); // 转换为毫秒
        }
    }

    // 如果视频流时长无效,则使用整个文件的时长
    if (format_ctx->duration != AV_NOPTS_VALUE) {
        return format_ctx->duration / 1000; // 转换为毫秒
    }

    return 0;
}

bool MP4Read::Seek(int64_t target_ms)
{
    if (!format_ctx || video_stream_index < 0) {
        LOG_ERROR("Format context or video stream not initialized");
        return false;
    }

    // 将目标时间从毫秒转换为视频流的时间基
    AVStream *video_stream = format_ctx->streams[video_stream_index];
    int64_t target_ts = av_rescale_q(target_ms, AVRational{1, 1000}, // 毫秒时间基
                                     video_stream->time_base);       // 视频流时间基

    // 执行跳转
    int ret = av_seek_frame(format_ctx.get(), video_stream_index, target_ts, AVSEEK_FLAG_BACKWARD);
    if (ret < 0) {
        char err_buf[AV_ERROR_MAX_STRING_SIZE] = {0};
        av_strerror(ret, err_buf, AV_ERROR_MAX_STRING_SIZE);
        LOG_ERROR("Failed to seek to position {} ms: {}", target_ms, err_buf);
        return false;
    }

    // 清空解码器缓冲
    if (video_codec_ctx) {
        avcodec_flush_buffers(video_codec_ctx.get());
    }
    if (audio_codec_ctx) {
        avcodec_flush_buffers(audio_codec_ctx.get());
    }

    // 重置首帧标志和pts时间
    is_first_video_frame = true;
    is_first_audio_frame = true;
    last_video_pts_ = 0;
    last_audio_pts_ = 0;

    LOG_DEBUG("Successfully seeked to {} ms", target_ms);
    return true;
}

bool MP4Read::Pause()
{
    LOG_INFO("MP4Read::Pause");
    if (!is_running.load() || is_paused_.load()) {
        return false;
    }
    is_paused_.store(true);
    return true;
}

bool MP4Read::Resume()
{
    LOG_INFO("MP4Read::Resume");
    if (!is_running.load() || !is_paused_.load()) {
        return false;
    }

    // 更新视频和音频的开始时间，减去当前帧的pts时间，这样可以立即发送当前帧
    auto now = std::chrono::steady_clock::now();
    if (video_stream_index >= 0) {
        video_start_time = now - std::chrono::microseconds(last_video_pts_);
    }
    if (audio_stream_index >= 0) {
        audio_start_time = now - std::chrono::microseconds(last_audio_pts_);
    }

    is_paused_.store(false);
    return true;
}

} // namespace Muxer
} // namespace El